//
// Created by zhouheyu on 17-12-2.
//

#include "AD_C2.h"
//创建双向链表,返回的是头节点
pNode CreateList()
{
    //分配初始内存
    pNode  pHead=(pNode)malloc(sizeof(Node));
    if(NULL==pHead){
        printf("malloc for pHead failed!\n");
        exit(-1);
    }
    pHead->LPN=-1;
    pHead->isD=-1;
    pHead->Pre=pHead;
    pHead->Next=pHead;

    return pHead;
}

pBNode CreateBIndex()
{
    int i;
    pBNode pHead=(pBNode)malloc(sizeof(BNode));
    if (NULL==pHead){
        printf("malloc for pBHead failed!\n");
        exit(-1);
    }
    pHead->BlkNum=-1;
    pHead->DirtyNum=0;
    pHead->CleanNum=0;
    pHead->Size=0;
    pHead->Pre=pHead;
    pHead->Next=pHead;
    for ( i = 0; i <PAGE_PRE_BLK ; ++i) {
        pHead->CleanList[i]=-1;
        pHead->DirtyList[i]=-1;
    }
    return pHead;
}

//删除整个链表，释放内存

void FreeList(pNode pHead)
{
    pNode ps,pt=pHead->Next;
    while(pt!=pHead){
        ps=pt;
        pt=pt->Next;
        free(ps);
    }
    free(pHead);
}

void FreeBList(pBNode pHead)
{
    pBNode ps,pt=pHead->Next;
    while(pt!=pHead){
        ps=pt;
        pt=pt->Next;
        free(ps);
    }
    free(pHead);
}

//初始化相应的配置参数
void InitVariable()
{
    buf_size=1024*4;
    //后续的统计变量
    buffer_cnt=0;
    buffer_hit=0;
    buffer_miss_cnt=0;
    buffer_read_hit=0;
    buffer_read_miss=0;
    buffer_write_hit=0;
    buffer_write_miss=0;
    //物理读写次数
    physical_read=0;
    physical_write=0;
    //设定当前的clru和dlru的长度
    CLRU_Length=0;
    DLRU_Length=0;
    BlkTable_Size=0;
    //设定当前的冷热比例的阈值
    Threshold=0.5;
    //初始化的tau
    Tau=buf_size/2;
    MinTauRatio=0.1;
    MaxTauRatio=0.9;
//    和周期更新Tau的数据相关
    CDHit_CWH=0;
    CDHit_CRH=0;
    CDHit_DRH=0;
    CDHit_DWH=0;
//    写入放大系数
    wAmp=1.35;
    UpdateTauCycle=buf_size*1;
    T_count=0;
    cycle_physical_write=0;
    cycle_physical_read=0;
    cycle_flash_write_delay=0.0;
    cycle_flash_read_delay=0.0;

}


//输出对应的统计结果
void PrintResultStat()
{
    //输出和缓冲区统计相关的信息
    printf("****************************************\n");
    printf("the all buffer req count is %d\n",buffer_cnt);
    printf("the buffer miss count is %d\n",buffer_miss_cnt);
    printf("the buffer hit count is %d\n",buffer_hit);
    printf("the hit rate is %f\n",((double)buffer_hit)/buffer_cnt);
    printf("the buffer read miss count is %d\n",buffer_read_miss);
    printf("the buffer write miss count is %d\n",buffer_write_miss);
    printf("the buffer read hit count is %d\n",buffer_read_hit);
    printf("the buffer write hit count is %d\n",buffer_write_hit);
    printf("the physical read count is %d\n",physical_read);
    printf("the physical write count is %d\n",physical_write);
}

void resetCacheStat()
{
    cache_read_num=0;
    cache_write_num=0;
}

double ComputeCacheDelay()
{
    double delay=0.0;
    double cache_read_delay=0.0;
    double cache_write_delay=0.0;
    cache_read_delay=(double)cache_read_num*(double)CACHE_READ_DELAY;
    cache_write_delay=(double)cache_write_num*(double)CACHE_WRITE_DELAY;
    delay=cache_read_delay+cache_write_delay;
    resetCacheStat();
    return delay;
}

//判断链表是否为空
int IsEmptyList(pNode pHead)
{
    pNode pt=pHead->Next;
    if(pt==pHead)
    {
        return 1;
    }else
    {
        return 0;
    }
}

//返回链表的长度
int GetListLength(pNode pHead)
{
    int length=0;
    pNode pt=pHead->Next;
    while (pt !=pHead)
    {
        length++;
        pt=pt->Next;
    }
    return length;
}

//返回链表的长度
int GetBIndexLength(pBNode pHead)
{
    int length=0;
    pBNode pt=pHead->Next;
    while (pt !=pHead)
    {
        length++;
        pt=pt->Next;
    }
    return length;
}

//输出打印链表
void PrintList(pNode pHead)
{
    pNode pt=pHead->Next;
    printf("the list is follow:\n");
    while(pt!=pHead)
    {
        printf("the LPN is %d\t",pt->LPN);
        printf("the isD is %d\n",pt->isD);
        pt=pt->Next;
    }
}

//从链表中插入新的节点,这里之后有读写操作的operation
int InsertEleList(pNode pHead,int pos,int LPN,int operation)
{
    pNode pt=NULL,p_new=NULL;
    pt=pHead->Next;
    if(pos>0&&pos<GetListLength(pHead)+2)
    {
        p_new=(pNode)malloc(sizeof(Node));
        if(NULL==p_new)
        {
            printf("malloc for New Node!\n");
            exit(-1);
        }

        while(1)
        {
            pos--;
            if(0==pos)
                break;
            pt=pt->Next;
        }
        //新建节点
        p_new->LPN=LPN;
        if(operation==0)
            p_new->isD=1;
        else
            p_new->isD=0;
        //这里的双链表是首位相接的，也就是head前面就是最后一个节点
        //插入pt的前面
        p_new->Pre=pt->Pre;
        p_new->Next=pt;
        //衔接
        pt->Pre->Next=p_new;
        pt->Pre=p_new;
        return 1;
    }else {
        return  0;
    }
}

//向链表中删除节点
int DeleteEleList(pNode pHead,int pos)
{
    pNode pt=pHead,ps=NULL;
    //pos=0就是pHead
    if(pos>0&&pos<GetListLength(pHead)+1){
        while(1)
        {
            pos--;
            if(pos==0)
                break;
            pt=pt->Next;
        }
        //此时的pt是pos的前一个节点
        //ps才是要删除的节点位置
        ps=pt->Next;
        pt->Next=ps->Next;
        ps->Next->Pre=pt;
        //释放ps指向的节点
        free(ps);
        return 1;
    }else{
        printf("delete pos %d is error\n",pos);
        return 0;
    }

}

//从链表中找到特定的LPN值，并返回节点的指针位置,如果不存在返回NULL
pNode FindLPNinList(pNode pHead,int LPN)
{
    pNode ps=NULL,pt=pHead->Next;
    int count=0;
    while(pt!=pHead)
    {
        count++;
        if(pt->LPN==LPN){
            ps=pt;
            break;
        }
        pt=pt->Next;
    }
    //调试输出语句遍历循环了多少次
//    printf("the while count is %d\n",count);
    return ps;
}

int myMax(int a,int b)
{
    if(a>b)
        return a;
    else
        return b;
}

int myMin(int a,int b)
{
    if(a>b)
        return b;
    else
        return a;
}

//该函数完成对目标Tau的自适应的更新
int UpdateTau()
{
    int D_Tau,TempTau,MinTau,MaxTau;//表示脏队列的目标长度
    //四射五入
    double B_CLRU,B_DLRU;//表示各自队列的单位收益
    MinTau=(int)(MinTauRatio*buf_size+0.5);
    MaxTau=(int)(MaxTauRatio*buf_size+0.5);
    D_Tau=buf_size-Tau;
    //未引入从底层得到flash读写延迟的代码
    B_CLRU=(CDHit_CWH*FLASH_WRITE_DELAY*wAmp+CDHit_CRH*FLASH_READ_DELAY)/Tau;
    B_DLRU=(CDHit_DWH*FLASH_WRITE_DELAY*wAmp+CDHit_DRH*FLASH_READ_DELAY)/D_Tau;
/*
    //如果从底层得到周期的读写时延
    ave_flash_read_delay=cycle_flash_read_delay/cycle_physical_read;
    ave_flash_write_delay=cycle_flash_write_delay/cycle_physical_write;
    B_CLRU=(CDHit_CRH*ave_flash_read_delay+CDHit_CWH*ave_flash_write_delay)/Tau;
    B_DLRU=(CDHit_DRH*ave_flash_read_delay+CDHit_CWH*ave_flash_write_delay)/D_Tau;
*/

    //四舍五入
    TempTau=(int)((B_CLRU/(B_CLRU+B_DLRU)*buf_size)+0.5);
    TempTau=myMax(MinTau,TempTau);
    TempTau=myMin(MaxTau,TempTau);
    Tau=TempTau;

    /*
    //适当的嵌入代码调试的测试语句
    printf("----------------------------------------------------------\n");
    printf("The Cycle Stat is:\n");
    printf("CLRU write Hit is %d\t Read Hit is %d\n",CDHit_CWH,CDHit_CRH);
    printf("DLRU write Hit is %d\t Read Hit is %d\n",CDHit_DWH,CDHit_DRH);
    printf("sum write delay is %f\t read delay is %f\n",cycle_flash_write_delay,cycle_flash_read_delay);
    printf("ave write delay is %f\t read delay is %f\n",ave_flash_write_delay,ave_flash_read_delay);
    printf("cycle physical write is %d\t physical read is %d\n",cycle_physical_write,cycle_physical_read);
    printf("-----------------------------------------------------------\n");
    */

    //重置相应的周期统计变量
    CDHit_CWH=0;
    CDHit_CRH=0;
    CDHit_DRH=0;
    CDHit_DWH=0;
    T_count=1;
    cycle_physical_write=0;
    cycle_physical_read=0;
    cycle_flash_write_delay=0.0;
    cycle_flash_read_delay=0.0;
    //返回更新后的Tau值，以备输出测试
    return Tau;
}

//找到块索引链表中的位置
pBNode FindBlkTable(pBNode Head,int BlkNum)
{
    pBNode ps=NULL,pt=Head->Next;
    int count=0;
    while(pt!=Head){
        if(pt->BlkNum==BlkNum){
            ps=pt;
            break;
        }
        count++;
        pt=pt->Next;
    }
    return ps;
}

//没有找到对应的数据则返回-1
int search_table(int *arr,int size,int val)
{
    int i;
    for (i = 0; i <size ; ++i) {
        if(arr[i]==val){
            return i;
        }
    }
    return -1;
}

int find_free_pos( int *arr, int size)
{
    int i;
    for(i = 0 ; i < size; i++) {
        if(arr[i] == -1) {
            return i;
        }
    }
    printf("shouldnt come here for find_free_pos()");
    exit(1);
    return -1;
}

//命中CLRU的操作,存在命中的请求类型
int HitCLRU(pNode CHead,pNode DHead,pNode pHit,int operation)
{
    pNode pt;
    pBNode pblk;
    int tempBlk,tempLPN;
    int victim,free_pos;
    tempLPN=pHit->LPN;
    tempBlk=tempLPN/PAGE_PRE_BLK;
//如果是写请求命中，则需要将对应的请求移动到DLRU的队列中
    if(0!=operation){
//      读命中
        buffer_read_hit++;
        cache_read_num++;
        CDHit_CRH++;
//       将命中的请求移动到CLRU的头部
        //从原先位置断开链接
        pt=pHit->Pre;
        pt->Next=pHit->Next;
        pHit->Next->Pre=pt;
//        插入位置
        pHit->Next=CHead->Next;
        pHit->Pre=CHead;
        CHead->Next->Pre=pHit;
        CHead->Next=pHit;
    }else{
//      写命中
        pHit->isD=1;
        buffer_write_hit++;
        cache_write_num++;
        CDHit_CWH++;
//       命中的数据移动到DLRU
//        从原来的位置断开
        pt=pHit->Pre;
        pt->Next=pHit->Next;
        pHit->Next->Pre=pt;
//        嵌入到DLRU的头部
        pHit->Pre=DHead;
        pHit->Next=DHead->Next;
        DHead->Next->Pre=pHit;
        DHead->Next=pHit;
        CLRU_Length--;
        DLRU_Length++;
//        更新对应的块索引
        pblk=FindBlkTable(BHead,tempBlk);
        if(pblk==NULL){
            printf("error happend in HitCLRU:\n");
            printf("can not find tempBlk %d in Blk-list\n",tempBlk);
            exit(-1);
        }
//       将对应的块索引中的标识改掉
        victim=search_table(pblk->CleanList,PAGE_PRE_BLK,tempLPN);
        if(victim==-1){
            printf("error happend in HitCLRU:\n");
            printf("can not find tempLPN%d in CleanList\n",tempLPN);
            exit(-1);
        }
        pblk->CleanList[victim]=-1;
        pblk->CleanNum--;
        free_pos=find_free_pos(pblk->DirtyList,PAGE_PRE_BLK);
        if(free_pos==-1){
            printf("error happend in HitCLRU:\n");
            printf("can not find free-pos for tempLPN%d in DirtyList\n",tempLPN);
            exit(-1);
        }
        pblk->DirtyList[free_pos]=tempLPN;
        pblk->DirtyNum++;
    }
    return 0;
}

//命中DLRU的操作
int HitDLRU(pNode DHead,pNode pHit,int operation)
{
    pNode pt=NULL;
    if(operation==0){
        buffer_write_hit++;
        cache_write_num++;
        CDHit_DWH++;
    } else{
        buffer_read_hit++;
        cache_read_num++;
        CDHit_DRH++;
    }
//    Move to MRU
    pt=pHit->Pre;
    //Del
    pt->Next=pHit->Next;
    pHit->Next->Pre=pt;
    //MRU
    pHit->Next=DHead->Next;
    pHit->Pre=DHead;
    DHead->Next->Pre=pHit;
    DHead->Next=pHit;
    return 0;
}

//删除CLRU中的数据，返回的是删除的LPN号
int DelCLRU(pNode CHead)
{
    pNode pt;
    pBNode pblk;
    int DelLPN=-1,tempBlk;
    int victim;

    pt=CHead->Pre;
    DelLPN=pt->LPN;
    tempBlk=DelLPN/PAGE_PRE_BLK;
    //错误判断
    if(pt==CHead){
        printf("error happend in DelCLRU\n");
        printf("CLRU list is empty!\n");
        exit(-1);
    }
//    删除尾部的数据
    pt->Pre->Next=CHead;
    CHead->Pre=pt->Pre;
//    释放该尾部的节点
    free(pt);
    CLRU_Length--;
//    错误判断
    if(CLRU_Length!=GetListLength(CHead)){
        printf("error happend in DelCLRU\n");
        printf("CLRU list size is error!\n");
        printf("CLRU list-size is %d\t,CLRU_Length is %d\n",GetListLength(CHead),CLRU_Length);
        exit(-1);
    }
//    更新对应的块索引
    pblk=FindBlkTable(BHead,tempBlk);
    if(pblk==NULL){
        printf("error happend in DelCLRU\n");
        printf("can not find tempBlk %d in Blk-list\n",tempBlk);
        exit(-1);
    }
    victim=search_table(pblk->CleanList,PAGE_PRE_BLK,DelLPN);
    if(victim==-1){
        printf("error happend in DelCLRU\n");
        printf("can not find DelLPN%d in Clean-list\n",DelLPN);
        exit(-1);
    }
    pblk->CleanList[victim]=-1;
    pblk->Size--;
    pblk->CleanNum--;

//    如果当前的块大小为0，说明不需要该块索引，直接删除即可
    if(pblk->Size==0){
        pblk->Pre->Next=pblk->Next;
        pblk->Next->Pre=pblk->Pre;
        //释放该节点
        free(pblk);
        BlkTable_Size--;
    }
//    错误调试
    if(BlkTable_Size!=GetBIndexLength(BHead)){
        printf("error happend in DelCLRU\n");
        printf("BlkTable Size is %d\t BIndex-list Size is %d\n",BlkTable_Size,GetBIndexLength(BHead));
        exit(-1);
    }

    return DelLPN;
}

//非聚簇删除DLRU的数据，设计回写操作，有时延
double DelOneDLRU(pNode DHead)
{
    double delay=0.0;
    pNode pt;
    pBNode pblk;
    int DelLPN=-1,tempBlk;
    int victim;

    pt=DHead->Pre;
    DelLPN=pt->LPN;
    tempBlk=DelLPN/PAGE_PRE_BLK;
    //错误判断
    if(pt==DHead){
        printf("error happend in DelOneDLRU\n");
        printf("DLRU list is empty!\n");
        exit(-1);
    }
//    删除尾部的数据
    pt->Pre->Next=DHead;
    DHead->Pre=pt->Pre;
//    释放该尾部的节点
    free(pt);
    DLRU_Length--;
//    错误判断
    if(DLRU_Length!=GetListLength(DHead)){
        printf("error happend in DelOneDLRU\n");
        printf("CLRU list size is error!\n");
        printf("DLRU list-size is %d\t,DLRU_Length is %d\n",GetListLength(DHead),DLRU_Length);
        exit(-1);
    }
//    更新对应的块索引
    pblk=FindBlkTable(BHead,tempBlk);
    if(pblk==NULL){
        printf("error happend in DelOneDLRU\n");
        printf("can not find tempBlk %d in Blk-list\n",tempBlk);
        exit(-1);
    }
    victim=search_table(pblk->DirtyList,PAGE_PRE_BLK,DelLPN);
    if(victim==-1){
        printf("error happend in DelOneDLRU\n");
        printf("can not find DelLPN%d in Dirty-list\n",DelLPN);
        exit(-1);
    }
    pblk->DirtyList[victim]=-1;
    pblk->Size--;
    pblk->DirtyNum--;

//    如果当前的块大小为0，说明不需要该块索引，直接删除即可
    if(pblk->Size==0){
        pblk->Pre->Next=pblk->Next;
        pblk->Next->Pre=pblk->Pre;
        //释放该节点
        free(pblk);
        BlkTable_Size--;
    }
//    错误调试
    if(BlkTable_Size!=GetBIndexLength(BHead)){
        printf("error happend in DelOneDLRU\n");
        printf("BlkTable Size is %d\t BIndex-list Size is %d\n",BlkTable_Size,GetBIndexLength(BHead));
        exit(-1);
    }




//    回写的时延
    physical_write++;
    cycle_physical_write++;
//    delay+=callFsim(DelLPN*4,4,0);
    delay=FLASH_WRITE_DELAY;
    cycle_flash_write_delay+=delay;

    return delay;
}

//find value in list pos-index,-1(no exist)
//pos--->0---Size-1
int FindValueInList(pNode Head,int Val)
{
	int pos=-1,count=0;
	pNode pt=Head->Next;
	while(pt!=Head){
		if(pt->LPN==Val){
			pos=count;
			break;
		}
		count++;
	}
	return pos;
}

//calculate nonegative value num in arr
int calculate_nonegative_arr(int *arr,int size)
{
	int i,count=0;
	for(i=0;i<size ;i++){
		if(arr[i]>=0){
			count++;
		}
	}
	return count;
}

//采用聚簇删除
double DelClusterInDLRU(pNode DHead)
{
    double delay=0.0;
    int VictimLPN,tempBlk,HotThreshold,temp_pos;
    pBNode pblk=NULL;
    pNode ptail=DHead->Pre,pDt,pDs;
    pVNode VHead=NULL,pt,ps;
    int V_Size;
    int count=0;
    
    VHead=(pVNode)malloc(sizeof(VNode));
    if(VHead==NULL){
		printf("error happen in DelClusterInDLRU\n");
		printf("malloc for  VHead failed\n");
		exit(-1);
	}
	VHead->LPN=-1;
	VHead->Next=VHead;
	VHead->Pre=VHead;
	VHead->pIndex=NULL;
	V_Size=0;
    
    VictimLPN=ptail->LPN;
    tempBlk=VictimLPN/PAGE_PRE_BLK;
    HotThreshold=Threshold*DLRU_Length;
    //test debug
    if(DLRU_Length!=GetListLength(DHead)){
		printf("error happen in DelClusterInDLRU\n");
		printf("DLRU -list-size is error\n");
		printf("DLRU-Size is %d\t DLRU_Length is %d\n",GetListLength(DHead),DLRU_Length);
		exit(-1);
	}
    
    //find tempBlk In BlkTable
    pblk=FindBlkTable(BHead,tempBlk);
    if(pblk==NULL){
		printf("error happen in DelClusterInDLRU\n");
		printf("can not find tempBlk %d in BlkTbale\n",tempBlk);
		exit(-1);
	}
	//debug
	if(pblk->DirtyNum!=calculate_nonegative_arr(pblk->DirtyList,PAGE_PRE_BLK)){
		printf("error happen in DelClusterInDLRU\n");
		printf("plbk-CleanNum is error:\n");
		printf("DirtyNum is %d\t Dirtylist-size is %d\n",pblk->DirtyNum,calculate_nonegative_arr(pblk->DirtyList,PAGE_PRE_BLK));
		exit(-1);
	}
	
	//find Victim LPN to form Vlist
	for(i=0,count=0;i<PAGE_PRE_BLK&&count<pblk->DirtyNum;i++){
		if(pblk->DirtyList[i]>=0){
			temp_pos=FindValueInList(DHead,pblk->DirtyList[i]);
			//debug
			if(temp_pos==-1){
				printf("error happen in DelClusterInDLRU\n");
				printf("can not find DLPN %d in DLRU-list\n",pblk->DirtyList[i]);
				exit(-1);
			}
			//pos later is Victim
			if(temp_pos>=HotThreshold){
				  V_Size++;
				  pt=NULL;
				  pt=(pVNode)malloc(sizeof(VNode));
				  if(pt==NULL){
					  printf("error happen in DelClusterInDLRU\n");
					  printf(" malloc for New VNode is failed\n");
					  exit(-1);
				  }
				  pt->LPN=pblk->DirtyList[i];
				  //Move pt To Vlist-MRU
				  ps=VHead->Next;
				  //embeded
				  pt->Next=ps;
				  pt->Pre=VHead;
				  //link
				  ps->Pre=pt;
				  VHead->Next=pt;
				  //find point for LPN
				  pt->pIndex=FindLPNinList(DHead,pt->LPN);
				  if(pt->pIndex==NULL){
					printf("error happen in DelClusterInDLRU\n");
					printf("can not find ponit for DLPN %d in DLRU-list\n",pt->LPN);  
				  }
			}
			
		}
	}//end-for
	// according to Vlist delete VLPN from DLRU
	ps=VHead->Next;
	for(i=0;i<V_Size;i++){
		//delete DLRU
		cycle_physical_write++;
		physical_write++;
		//pDt is victim point
		pDt=ps->pIndex;
		pDs=pDt->Pre;
		pDs->Next=pDt->Next;
		pDt->Next->Pre=pDs;
		free(pDt);
		DLRU_Length--;
		delay+=FLASH_WRITE_DELAY;
	//  delay+=callFsim(ps->LPN*4,4,0);
		cycle_flash_write_delay+=delay;
		//find next victim 
		ps=ps->Next;
	}
    
    return delay;
}


//将新的请求加入到缓冲区,涉及到物理读操作，有延迟
double AddNewToBuffer(pNode CHead,pNode DHead,int LPN,int operation)
{
    double delay=0.0;
    pNode pt;
    pBNode pblk,ptblk;
    int tempBlk;
    int i,free_pos;
    tempBlk=LPN/PAGE_PRE_BLK;
    //    错误检测
    if(BlkTable_Size!=GetBIndexLength(BHead)){
        printf("error happend in AddNewToBuffer 1\n");
        printf("BlkTable Size is %d\t BIndex-list Size is %d\n",BlkTable_Size,GetBIndexLength(BHead));
        exit(-1);
    }

    pblk=FindBlkTable(BHead,tempBlk);

    if(pblk==NULL){
//       第一次加载该数据块没，添加其到链表中
        pblk=(pBNode)malloc(sizeof(BNode));
        if (NULL==pblk){
            printf("error happend in AddNewToBuffer\n");
            printf("malloc for pblk failed!\n");
            exit(-1);
        }
        pblk->BlkNum=tempBlk;
        pblk->DirtyNum=0;
        pblk->CleanNum=0;
        pblk->Size=0;
        for ( i = 0; i <PAGE_PRE_BLK ; ++i) {
            pblk->CleanList[i]=-1;
            pblk->DirtyList[i]=-1;
        }
//        将新的节点链接头部
        ptblk=BHead->Next;
//        插入关联
        pblk->Pre=BHead;
        pblk->Next=ptblk;
//        链接
        ptblk->Pre=pblk;
        BHead->Next=pblk;
        BlkTable_Size++;
    }

//   为新的节点分配内存
    pt=(pNode)malloc(sizeof(Node));
    if(pt==NULL){
        printf("error happend in AddNewToBuffer\n");
        printf("malloc for pNode failed!\n");
        exit(-1);
    }
    pt->LPN=LPN;
    physical_read++;
    cycle_physical_read++;
//    delay=callFsim(LPN*4,4,1);
    delay=FLASH_READ_DELAY;
    cycle_flash_read_delay+=delay;

//   根据不同的请求将数据页加载到对应的队列中
    if(operation==0){
        buffer_write_miss++;
        cache_write_num++;
        pt->isD=1;
//        Move to MRU
        pt->Pre=DHead;
        pt->Next=DHead->Next;
        DHead->Next->Pre=pt;
        DHead->Next=pt;
        DLRU_Length++;
//        更新对应的块索引
        free_pos=find_free_pos(pblk->DirtyList,PAGE_PRE_BLK);
        if(free_pos==-1){
            printf("error happend in AddNewToBuffer:\n");
            printf("can not find free-pos for tempLPN%d in DirtyList\n",LPN);
            exit(-1);
        }
        pblk->DirtyList[free_pos]=LPN;
        pblk->Size++;
        pblk->DirtyNum++;

    }else{
        buffer_read_miss++;
        cache_read_num++;
        pt->isD=0;
//        Move To CLRU MRU
        pt->Pre=CHead;
        pt->Next=CHead->Next;
        CHead->Next->Pre=pt;
        CHead->Next=pt;
        CLRU_Length++;
//        更新对应的块索引
        free_pos=find_free_pos(pblk->CleanList,PAGE_PRE_BLK);
        if(free_pos==-1){
            printf("error happend in AddNewToBuffer:\n");
            printf("can not find free-pos for tempLPN%d in CleanList\n",LPN);
            exit(-1);
        }
        pblk->CleanList[free_pos]=LPN;
        pblk->Size++;
        pblk->CleanNum++;
    }

//    错误检测
    if(CLRU_Length!=GetListLength(CHead)||DLRU_Length!=GetListLength(DHead)){
        printf("error happend in AddNewToBuffer:\n");
        printf("CLRU_Length is %d\t Clru-list size is %d\n",CLRU_Length,GetListLength(CHead));
        printf("DLRU_Length is %d\t Clru-list size is %d\n",DLRU_Length,GetListLength(DHead));
        exit(-1);
    }
//    错误检测
    if(BlkTable_Size!=GetBIndexLength(BHead)){
        printf("error happend in AddNewToBuffer 2\n");
        printf("BlkTable Size is %d\t BIndex-list Size is %d\n",BlkTable_Size,GetBIndexLength(BHead));
        exit(-1);
    }

    return delay;
}


int ZJ_flag=0;
//观测输出的变量
int ObserveCycle=100;
int CycleCount=0;
double DelaySum=0.0;
double AveDelay=0.0;
//last
int Last_buffer_read_miss=0;
int Last_bufer_write_miss=0;
int Last_buffer_cnt=0;
int Last_buffer_miss_cnt=0;
//curr
int Curr_buffer_read_miss;
int Curr_buffer_write_miss;
int Curr_buffer_cnt;
int Curr_buff_miss_cnt;



double CacheManage(int secno,int scount,int operation )
{
    double delay=0.0;
    double flash_delay=0.0, cache_delay=0.0;
    pNode pt=NULL;
    int tempBlk;
    int flag=0;//flag=0表示未命中缓冲区，1命中CLRU，2命中DLRU
    int blkno,cnt,bcount;
//    进行页对齐
    blkno = secno / SEC_PRE_PAGE;
    bcount = (secno + scount - 1) / SEC_PRE_PAGE - (secno) / SEC_PRE_PAGE + 1;
    cnt=bcount;
//   第一次调用该函数，则进行初始化
    if(ZJ_flag==0){
        CHead=CreateList();
        DHead=CreateList();
        BHead =CreateBIndex();
        InitVariable();
        ZJ_flag=1;
    }
    while(cnt>0){
        buffer_cnt++;
        tempBlk=blkno/PAGE_PRE_BLK;
//        查看是否在缓冲区中，命中缓冲区（存在CLRU移动到DLRU）
        flag=0;
        pt=FindLPNinList(CHead,blkno);
        if(pt!=NULL){
//         命中CLRU
            flag=1;
        } else{
//          未命中DLRU,查看是否命中DLRU
            pt=FindLPNinList(DHead,blkno);
            if(pt!=NULL){
//                命中DLRU
                flag=2;
            }
        }
//      针对不同的命中队列调用不同的操作函数
        if(pt!=NULL){
            buffer_hit++;
            if(flag==1){
//                命中CLRU
                HitCLRU(CHead,DHead,pt,operation);
            }else
            {
//             命中DLRU
                HitDLRU(DHead,pt,operation);
            }
        } else {
//        没有命中缓冲区，根据Tau值选择剔除队列
            buffer_miss_cnt++;
            if(CLRU_Length+DLRU_Length>=buf_size){
                if(CLRU_Length>Tau){
//                    删除CLRU中的数据项
                    DelCLRU(CHead);
                }else{
//                    删除DLRU中的数据项
                    flash_delay+=DelOneDLRU(DHead);
                }
            }
//        加载新的数据到缓冲区
            flash_delay+=AddNewToBuffer(CHead,DHead,blkno,operation);
        }
//      看是否触发，更新Tau的更新机制
        if(T_count==UpdateTauCycle){
            UpdateTau();
        }else {
            T_count++;
        }

        blkno++;
        cnt--;
    }

    //返回计算请求的时延
    cache_delay=ComputeCacheDelay();
    delay=cache_delay+flash_delay;
    //周期观测数据的输出
    if(0 == CycleCount % ObserveCycle && CycleCount != 0){
        AveDelay=DelaySum/ObserveCycle;
        DelaySum=0.0;
        printf("the %d Request,the AveDelay is %f\n",CycleCount,AveDelay);
        Curr_buff_miss_cnt=buffer_miss_cnt-Last_buffer_miss_cnt;
        Curr_buffer_cnt=buffer_cnt-Last_buffer_cnt;
        Curr_buffer_read_miss=buffer_read_miss-Last_buffer_read_miss;
        Curr_buffer_write_miss=buffer_write_miss-Last_bufer_write_miss;
        printf("the Curr_buff_cnt is %d\tbuffer miss cnt is %d\n",Curr_buffer_cnt,Curr_buff_miss_cnt);
        printf("the Curr buff read miss is %d\t write miss is %d\n",Curr_buffer_read_miss,Curr_buffer_write_miss);
        Last_buffer_cnt=buffer_cnt;
        Last_buffer_miss_cnt=buffer_miss_cnt;
        Last_buffer_read_miss=buffer_read_miss;
        Last_bufer_write_miss=buffer_write_miss;
        printf("Curr Tau is %d\n",Tau);
        printf("..............................................................\n");
        CycleCount++;
    }else{
        DelaySum+=delay;
        CycleCount++;
    }

    return delay;
}
